<?php
/**
 * @package    appearance
 * @subpackage appearance.api
 * @author     Nam Nguyen <nam.ngvan@gmail.com>
 * @version    1.0
 * @since      Apr 17, 2013
 */
class Core_Api_Menu
{
	/**
	 * get Render
	 *
	 * @return Nuo_Menu_Render_Abstract
	 */
	function getRender()
	{
		return new Nuo_Menu_Render_Default;
	}

	/**
	 * @return string
	 */
	public function render($key, $config = NULL)
	{
		$data = $this -> loadData($key);

		if (!$data or !isset($data['items']))
		{
			return '';
		}
		if(!$config){
			$config  = $data['extra'];
		}
		return $this -> getRender() -> render($data['items'], 0, $config);
	}

	function fetchItems($name)
	{
		// reprocess this type of data.
		$table = Nuo::getTable('core/menu');

		$menu = $table -> fetchRow($table -> select() -> where('menu_key=?', (string)$name));

		if (NULL == $menu)
		{
			return array();
		}

		$table = Nuo::getTable('core/menuitem');

		$select = $table -> select() -> where('menu_id=?', $menu -> getId()) -> where('is_enabled=?', 1) -> order('sort_order ASC');

		return $table -> fetchAll($select);
	}

	/**
	 * @param string $menuKey
	 * @return array
	 */
	public function loadData($menuKey)
	{

		$cacheKey = 'core/ape/menu/' . $menuKey;

		$data = Nuo_Cache::instance() -> read($cacheKey);

		if (FALSE === $data)
		{
			$data = $this -> loadDataFromDB($menuKey);
			Nuo_Cache::instance() -> write($cacheKey, $data);
		}
		return $data;
	}

	/**
	 * @param string  $menuKey
	 * @return array
	 */
	public function loadDataFromDB($menuKey)
	{
		// reprocess this type of data.
		$table = Nuo::getTable('core/menu');

		$menu = $table -> fetchRow($table -> select() -> where('menu_key=?', (string)$menuKey));

		if (null == $menu)
		{
			return array();
		}

		$table = Nuo::getTable('core/menuitem');

		$select = $table -> select() -> where('menu_id=?', $menu -> getId()) -> where('is_enabled=?', 1) -> order('sort_order ASC');

		$temp_items = $table -> fetchAll($select) -> toArray();

		// final list of items.
		$items = array();

		// map parent_item_id => parent_id
		foreach ($temp_items as $item)
		{
			$extra = (array)json_decode($item['extra'], 1);

			if (!isset($extra['li']))
			{
				$extra['li'] = array();
			}
			if (!isset($extra['ul']))
			{
				$extra['ul'] = array();
			}

			if (!isset($extra['a']))
			{
				$extra['a'] = array();
			}

			$item['extra'] = $extra;

			$items[$item['item_id']] = $item;
		}

		unset($temp_items);

		for ($i = 0; $i < 10; ++$i)
		{

			// define some thing else.
			$map_p2c = array();
			$found = false;

			// map parent_item_id => parent_id
			foreach ($items as $item)
			{
				$map_p2c[$item['parent_id']] = 1;
			}

			foreach ($items as $key => $item)
			{
				$id = $item['item_id'];
				$pid = $item['parent_id'];

				// process p1.
				if (0 == $pid)
				{
					continue;
				}

				if (!isset($map_p2c[$id]) && $map_p2c[$pid] == 1)
				{
					$found = true;
					if (isset($items[$pid]) && is_array($items[$pid]))
					{
						$items[$pid]['items'][] = $item;
					}
					unset($items[$key]);
				}
				else
				{
					// temporary block parent node.
					$map_p2c[$pid] = 2;
				}
			}
			if (!$found)
			{
				break;
			}
		}

		$extra = json_decode($menu -> extra, 1);

		$data = array(
			'extra' => $extra,
			'clearfix' => $menu -> clearfix,
			'items' => $items,
		);
		// reprocess this type of data.
		$table = Nuo::getTable('core/menu');

		$menu = $table -> fetchRow($table -> select() -> where('menu_key=?', (string)$menuKey));

		if (null == $menu)
		{
			return array();
		}

		$table = Nuo::getTable('core/menuitem');

		$select = $table -> select() -> where('menu_id=?', $menu -> getId()) -> where('is_enabled=?', 1) -> order('sort_order ASC');

		$temp_items = $table -> fetchAll($select) -> toArray();

		// final list of items.
		$items = array();

		// map parent_item_id => parent_id
		foreach ($temp_items as $item)
		{
			$extra = (array)json_decode($item['extra'], 1);

			if (!isset($extra['li']))
			{
				$extra['li'] = array();
			}
			if (!isset($extra['ul']))
			{
				$extra['ul'] = array();
			}

			if (!isset($extra['a']))
			{
				$extra['a'] = array();
			}

			$item['extra'] = $extra;

			$items[$item['item_id']] = $item;
		}

		unset($temp_items);

		for ($i = 0; $i < 10; ++$i)
		{

			// define some thing else.
			$map_p2c = array();
			$found = false;

			// map parent_item_id => parent_id
			foreach ($items as $item)
			{
				$map_p2c[$item['parent_id']] = 1;
			}

			foreach ($items as $key => $item)
			{
				$id = $item['item_id'];
				$pid = $item['parent_id'];

				// process p1.
				if (0 == $pid)
				{
					continue;
				}

				if (!isset($map_p2c[$id]) && $map_p2c[$pid] == 1)
				{
					$found = true;
					if (isset($items[$pid]) && is_array($items[$pid]))
					{
						$items[$pid]['items'][] = $item;
					}
					unset($items[$key]);
				}
				else
				{
					// temporary block parent node.
					$map_p2c[$pid] = 2;
				}
			}
			if (!$found)
			{
				break;
			}
		}

		$extra = json_decode($menu -> extra, 1);

		$data = array(
			'extra' => $extra,
			'clearfix' => $menu -> clearfix,
			'items' => $items,
		);

		return $data;
	}

}
